package com.dbflow5.query;

import com.dbflow5.StringUtils;
import com.dbflow5.query.property.IProperty;
import com.dbflow5.sql.Query;

/**
 * Description: Describes an easy way to create a SQLite TRIGGER
 */
public class Trigger implements Query {
    /**
     * Specifies that we should do this TRIGGER before some event
     */
    public static final String BEFORE = "BEFORE";

    /**
     * Specifies that we should do this TRIGGER after some event
     */
    public static final String AFTER = "AFTER";

    /**
     * Specifies that we should do this TRIGGER instead of the specified events
     */
    public static final String INSTEAD_OF = "INSTEAD OF";

    String name;
    /**
     * If it's [.BEFORE], [.AFTER], or [.INSTEAD_OF]
     */
    private String beforeOrAfter = "";

    private boolean temporary = false;

    public Trigger(String name){
        this.name = name;
    }

    @Override
    public String getQuery(){
        StringBuilder queryBuilder = new StringBuilder("CREATE ");
        if (temporary) {
            queryBuilder.append("TEMP ");
        }
        queryBuilder.append("TRIGGER IF NOT EXISTS ");
        StringUtils.appendQuotedIfNeeded(queryBuilder, name);
        queryBuilder.append(" ");
        StringUtils.appendOptional(queryBuilder,beforeOrAfter + " ");

        return queryBuilder.toString();
    }

    /**
     * Sets the trigger as temporary.
     * @return this
     */
    public Trigger temporary() {
        this.temporary = true;
        return this;
    }

    /**
     * Specifies AFTER eventName
     * @return this
     */
    public Trigger after() {
        beforeOrAfter = AFTER;
        return this;
    }

    /**
     * Specifies BEFORE eventName
     * @return this
     */
    public Trigger before() {
        beforeOrAfter = BEFORE;
        return this;
    }

    /**
     * Specifies INSTEAD OF eventName
     * @return this
     */
    public Trigger insteadOf() {
        beforeOrAfter = INSTEAD_OF;
        return this;
    }

    /**
     * Starts a DELETE ON command
     *
     * @param onTable The table ON
     * @return TriggerMethod
     */
    public <TModel> TriggerMethod<TModel>  deleteOn(Class<TModel> onTable) {
        return new TriggerMethod<>(this, TriggerMethod.DELETE, onTable);
    }

    /**
     * Starts a INSERT ON command
     *
     * @param onTable The table ON
     * @return TriggerMethod
     */
    public <TModel> TriggerMethod<TModel> insertOn(Class<TModel> onTable) {
        return new TriggerMethod<>(this, TriggerMethod.INSERT, onTable);
    }

    /**
     * Starts an UPDATE ON command
     *
     * @param onTable    The table ON
     * @param properties if empty, will not execute an OF command. If you specify columns,
     * the UPDATE OF column1, column2,... will be used.
     * @return TriggerMethod
     */
    public <TModel> TriggerMethod<TModel> updateOn(Class<TModel> onTable, IProperty<?>... properties) {
        return new TriggerMethod<>(this, TriggerMethod.UPDATE, onTable, properties);
    }

    /**
     * Create new instance of trigger
     * @param triggerName The name of the trigger to use.
     * @return A new trigger.
     */
    public static Trigger create(String triggerName) {
        return new Trigger(triggerName);
    }
}
